package controller;

import util.JDBCUtils;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用表数据增删改查功能类
 */
public class DataAccessHandler {

    /**
     * 查询表中的单条记录，以bean对象返回
     * @param clazz 表对应类
     * @param sql sql命令
     * @param params 占位符参数列表
     * @return bean对象
     * @param <T> 泛型
     */
    public static <T> T queryOne(Class<T> clazz, String sql, Object ... params){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }    //3.执行sql语句，处理返回结果集
            rs = ps.executeQuery();
            if (rs.next()){ //若结果集不为空
                //创建bean对象
                T newInstance = clazz.newInstance();
                //获取元数据
                ResultSetMetaData md = rs.getMetaData();
                int columnCount = md.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    //获取列别名
                    String columnLabel = md.getColumnLabel(i);
                    //获取列值
                    Object columnValue = rs.getObject(i);
                    //通过反射给对象属性赋值
                    Field field;
                    try{
                        field = clazz.getDeclaredField(columnLabel);
                    }catch (NoSuchFieldException e){
                        //如果当前类没找到此属性，就去父类中找
                        field = clazz.getSuperclass().getDeclaredField(columnLabel);
                        //note：反射获取继承的属性需要通过父类的运行时类对象
                    }
                    field.setAccessible(true); //开启私有字段访问权限
                    field.set(newInstance,columnValue);
                }

                return newInstance;
            }
        } catch (SQLException | InstantiationException | IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        } finally {
            //4.关闭连接资源
            JDBCUtils.closeResource(rs,ps,conn);
        }
        return null;
    }

    /**
     * 查询表中的多条记录，以bean列表返回
     * @param clazz 表对应类
     * @param sql sql语句
     * @param params 占位符参数列表
     * @return bean对象列表
     * @param <T> 泛型
     */
    public static <T> List<T> query(Class<T> clazz, String sql, Object ... params){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            //3.执行sql语句，处理返回结果集
            ArrayList<T> list = new ArrayList<>(); //bean对象列表
            rs = ps.executeQuery();
            while (rs.next()){
                //创建bean对象
                T newInstance = clazz.newInstance();
                //获取元数据
                ResultSetMetaData md = rs.getMetaData();
                int columnCount = md.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    //获取列别名
                    String columnLabel = md.getColumnLabel(i);
                    //获取列值
                    Object columnValue = rs.getObject(i);
                    //通过反射给对象属性赋值
                    Field field;
                    try{
                        field = clazz.getDeclaredField(columnLabel);
                    }catch (NoSuchFieldException e){
                        //如果当前类没找到此属性，就去父类中找
                        field = clazz.getSuperclass().getDeclaredField(columnLabel);
                        //note：反射获取继承的属性需要通过父类的运行时类对象
                    }
                    field.setAccessible(true); //开启私有字段访问权限
                    field.set(newInstance,columnValue);
                }
                list.add(newInstance);
            }
            return list;
        } catch (SQLException | InstantiationException | IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        } finally {
            //4.关闭连接资源
            JDBCUtils.closeResource(rs,ps,conn);
        }
        return null;
    }

    /**
     * 更新表数据
     * @param sql sql语句
     * @param params 占位符参数列表
     * @return 更新状态
     */
    public static boolean update(String sql, Object ... params){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            //3.执行sql语句
            ps.execute();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //4.关闭连接资源
            JDBCUtils.closeResource(ps,conn);
        }
        return false;
    }
}
